home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 1471 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.6 KB  |  100 lines

  1. Path: newshost.lanl.gov!tanmoy
  2. From: tanmoy@qcd.lanl.gov (Tanmoy Bhattacharya)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: void pointers
  5. Date: 14 Jan 1996 05:49:57 GMT
  6. Organization: Los Alamos National Laboratory
  7. Message-ID: <TANMOY.96Jan13224957@qcd.lanl.gov>
  8. References: <1996Jan12.133322.1@ccc.govt.nz> <4d8j83$n3@s02.pavilion.co.uk>
  9. NNTP-Posting-Host: qcd.lanl.gov
  10. Mime-Version: 1.0
  11. Content-Type: text
  12. In-reply-to: AJRobb@pavilion.co.uk's message of Sat, 13 Jan 1996 15:32:15 GMT
  13.  
  14. --text follows this line--
  15. In article <4d8j83$n3@s02.pavilion.co.uk> AJRobb@pavilion.co.uk (Andy
  16. J Robb) writes: 
  17. <snip>
  18.    >    void getFence (void **clipPP);
  19. <snip>
  20.    YourType *clipP;    /* set up an unitialized pointer */
  21.    getFence(&clipP);    /* initialize it in the functions */
  22.  
  23. This is wrong (unless YourType is actually void). This is a very
  24. common misconception however, despite the FAQ: and so I am following
  25. up. Please read the FAQ before posting.
  26.  
  27.    >2) What is actually going on?
  28.  
  29.    The (void*) type is a dirty catch-all pointer.  It can point to
  30.    anything but you must cast it or assign it to something else before
  31.    you use it.
  32.  
  33. Almost. But this does not mean that void* has the same size and
  34. representation as every other pointer! Declaring something as void*
  35. tells the compiler to set aside enough space to record information
  36. about any kind of data pointer. When you assign some other kind of
  37. pointer to it, the compiler _converts_ the internal representation of
  38. that pointer to the `generic' void* format. Similarly, when assigning
  39. void* to anything else, the compiler converts from the generic format
  40. to the format for the speicific type in question. Naturally, to do
  41. this, the compiler needs to know that it is doing a conversion, what
  42. it is converting from, and what it is converting to.
  43.  
  44. Now see what happens in the following:
  45.  
  46. void f(void** x) { *x = 0; }
  47. void g(void*  x) { x  = 0; }
  48. void h(void*  x) { double*z=x; *z = 0;}
  49. int main(void) { int *y; f(&y); g(y); h(y); return 0; } /* Invalid code */
  50.  
  51. When the compiler is compiling f, it knows that it has to store a null
  52. pointer into *x. But which representation of the null pointer? The
  53. answer obviously is the generic `void*' representation.
  54.  
  55. On the other hand, if the call to f in main would have been valid, *x
  56. is but y, and the values in y are interpreted to be of type int*. Note
  57. that f stored the `void*' representation of a null pointer into this
  58. space: but, for all we know, void* does not even fit into an int*
  59. variable. And naturally, f could not have stored an int*, because it
  60. did not _know_ that *x can be an int*!!! So, the standard states that
  61. the compiler _must_ diagnose this misuse.
  62.  
  63. Note now the case of g. This call is perfectly valid. This also stores
  64. the void* representation of the null pointer; but into x --- which
  65. because of the call by value convention of C, is not the same as y! It
  66. is only that y is used to initialize a truly independent void*
  67. variable x, and the format convertion from int* to void* happens
  68. during this initialization.
  69.  
  70. The case of h is again different. In this case, the double
  71. representation of 0 is put into *z, where z is initialized from x
  72. (thorigh the void* ---> double* format conversion). This is an
  73. error!!! because x is actually the generic representation of something
  74. that points to an int, and not something that points to a double. This
  75. error however does not need to be diagnosed by the compiler: showing
  76. thus that void* ---> non-void* is a dangerous conversion. In the
  77. related language C++, this is therefore prohibited in the absence of a
  78. cast. In C, one chooses ease of use over safety.
  79.  
  80.    In my example, I have shown that I have a pointer to a type
  81.    (YourType).  This allows the returned pointer to be used without
  82.    casting.  I then passed the address OF this pointer (rather than the
  83.    address held by the pointer) to the function, getFence().  The
  84.    prototype declaration of getFence() will cause an implicit cast to
  85.    (void**) in the call.  The function, getFence(), then does its
  86.    business and returns the address of the result in the pointer, clipP.
  87.    It can do this because you gave it the address of clipP.
  88.  
  89. But as my analysis above demonstrates, the code is wrong.
  90.  
  91. Cheers
  92. Tanmoy
  93. --
  94. tanmoy@qcd.lanl.gov(128.165.23.46) DECNET: BETA::"tanmoy@lanl.gov"(1.218=1242)
  95. Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87545 H:#9,3000,Trinity Drive,NM87544
  96. Others see <gopher://yaleinfo.yale.edu:7700/00/Internet-People/internet-mail>,
  97. <http://alpha.acast.nova.edu/cgi-bin/inmgq.pl>or<ftp://csd4.csd.uwm.edu/pub/
  98. internetwork-mail-guide>. -- <http://nqcd.lanl.gov/people/tanmoy/tanmoy.html>
  99. fax: 1 (505) 665 3003   voice: 1 (505) 665 4733    [ Home: 1 (505) 662 5596 ]
  100.